﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Furion.DatabaseAccessor;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using YShop.Application.Contracts.System.DataItems;
using YShop.Core.Managers.Caches;
using YShop.Core.System;
using YShop.Core;
using YShop.Application.Contracts.Views;
using System.Reflection;

namespace YShop.Application.System
{
    /// <summary>
    /// 数据项服务
    /// </summary>
    [ApiDescriptionSettings("System")]
    [Route("api/data/item")]
    public class DataItemService : CrudService<DataItem, DataItemDto, DataItemDto, DataItemPageSearchDto, DataItemDto, DataItemDto>,IBaseService
    {
        private readonly IRepository<DataItem> _repository;
        private readonly CacheManager _cache;
        private readonly SystemDataItemService _systemDataItemService;

        public override List<DataItem> EntitiesCache => _cache.GetOrCreate(CacheKeys.DataItems, _ =>
        {
            var data = _repository.Include(s => s.Details, false).ToList();
            data.AddRange((_systemDataItemService.SystemDataItems).Adapt<List<DataItem>>());
            return data;
        });
        public override string EntitiesCacheKey => CacheKeys.DataItems;

        public DataItemService(
            IRepository<DataItem> repository,
            CacheManager cache,
            SystemDataItemService systemDataItemService)
            : base(repository)
        {
            _repository = repository;
            _cache = cache;
            _systemDataItemService = systemDataItemService;

        }


        /// <summary>
        /// 查询单个
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public override async Task<DataItemDto> GetAsync(string id)
        {
            return await Task.FromResult(EntitiesCache.FirstOrDefault(s => s.Id == id).Adapt<DataItemDto>());
        }

        /// <summary>
        /// 根据代码获取字典项
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        [Route("/api/data/items/{code}")]
        public async Task<List<DataItemDetailDto>> GetItems(string code)
        {
            return await Task.FromResult(EntitiesCache.FirstOrDefault(s => s.Code == code)?.Details?.Adapt<List<DataItemDetailDto>>());
        }

        /// <summary>
        /// 根据代码获取字典项
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        [Route("/api/data/cascade/{code}")]
        public async Task<List<Cascader>> GetCascades(string code)
        {
            var item = EntitiesCache.FirstOrDefault(s => s.Code == code).Adapt<DataItemDto>();
            if(item == null)
            {
                //if(item.Type == DataItemType.Dict)
                //{
                //    return await Task.FromResult(item.Details.Adapt<List<Cascader>>());
                //}

                //if(item.Type == DataItemType.Source)
                //{
                //    var action = (MethodInfo)item.Details;

                //}
                return await Task.FromResult(await _systemDataItemService.GetAction(code));
            }
            else
            {
                return await Task.FromResult(item.Details.Adapt<List<Cascader>>());
            }
        }

        /// <summary>
        /// 查询列表
        /// </summary>
        /// <param name="searchDto"></param>
        /// <returns></returns>
        [Route("list")]
        public override async Task<PagedList<DataItemDto>> GetListAsync([FromQuery] DataItemPageSearchDto searchDto)
        {
            var query = new ExpressionBuilder<DataItemDto>();
            if(!string.IsNullOrEmpty(searchDto.CategoryId))
            {
                query.And(s=>s.CategoryId == searchDto.CategoryId);
            }
            return await EntitiesCache.ToPageListAsync(searchDto.PageIndex, searchDto.PageSize, query);
        }

    }


    /// <summary>
    /// 数据项分类
    /// </summary>
    [ApiDescriptionSettings("System")]
    [Route("api/data/item/category")]
    public class DataItemCategoryService
        : CrudService<DataItemCategory, DataItemCategoryDto, DataItemCategoryDto, PageSearchDto, DataItemCategoryDto, DataItemCategoryDto>, IBaseService
    {
        private readonly IRepository<DataItemCategory> _repository;
        private readonly CacheManager _cacheManager;

        public override List<DataItemCategory> EntitiesCache => _cacheManager.GetOrCreate(CacheKeys.DataItemCategorys, _ => _repository.AsEnumerable(false));
        public override string EntitiesCacheKey => CacheKeys.DataItemCategorys;

        public DataItemCategoryService(IRepository<DataItemCategory> repository,CacheManager cacheManager) 
            : base(repository)
        {
            _repository = repository;
            _cacheManager = cacheManager;
        }

        /// <summary>
        /// 获取树形
        /// </summary>
        /// <returns></returns>
        [SystemDataItem(code: "DataItemCategoryCascaders", type: DataItemDetailsDataType.Cascade)]
        public List<Cascader> GetTrees()
        {
            var config = new TypeAdapterConfig();
            config.ForType<DataItemCategory, Cascader>()
                .Map(dist => dist.Label, src => src.Name)
                .Map(d => d.Value, s => s.Id);

            var categorys = EntitiesCache.Adapt<List<Cascader>>(config);
            var results = new List<Cascader>();
            foreach(var category in categorys)
            {
                var parent = categorys.FirstOrDefault(s => s.Id == category.ParentId);
                if (parent != null)
                {
                    parent.Children ??= new List<Cascader>();
                    parent.Children.Add(category);
                }
                else
                {
                    results.Add(category);
                }
            }
            return results;
        }
    }


    /// <summary>
    /// 数据项明细
    /// </summary>
    [ApiDescriptionSettings("System")]
    [Route("api/data/item/detail")]
    public class DataItemDetailService
        : CrudService<DataItemDetail, DataItemDetailDto, DataItemDetailDto, PageSearchDto, DataItemDetailDto, DataItemDetailDto>, IBaseService
    {
        public DataItemDetailService(IRepository<DataItemDetail> repository) : base(repository)
        {
        }
    }
}
